home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 3.iso / dist / fw_qt3.idb / usr / freeware / Qt / tutorial / t14 / cannon.cpp.z / cannon.cpp
C/C++ Source or Header  |  2002-04-08  |  6KB  |  293 lines

  1. /****************************************************************
  2. **
  3. ** Implementation CannonField class, Qt tutorial 14
  4. **
  5. ****************************************************************/
  6.  
  7. #include "cannon.h"
  8. #include <qtimer.h>
  9. #include <qpainter.h>
  10. #include <qpixmap.h>
  11. #include <qdatetime.h>
  12.  
  13. #include <math.h>
  14. #include <stdlib.h>
  15.  
  16.  
  17. CannonField::CannonField( QWidget *parent, const char *name )
  18.         : QWidget( parent, name )
  19. {
  20.     ang = 45;
  21.     f = 0;
  22.     timerCount = 0;
  23.     autoShootTimer = new QTimer( this, "movement handler" );
  24.     connect( autoShootTimer, SIGNAL(timeout()),
  25.          this, SLOT(moveShot()) );
  26.     shoot_ang = 0;
  27.     shoot_f = 0;
  28.     target = QPoint( 0, 0 );
  29.     gameEnded = FALSE;
  30.     barrelPressed = FALSE;
  31.     setPalette( QPalette( QColor( 250, 250, 200) ) );
  32.     newTarget();
  33. }
  34.  
  35.  
  36. void CannonField::setAngle( int degrees )
  37. {
  38.     if ( degrees < 5 )
  39.     degrees = 5;
  40.     if ( degrees > 70 )
  41.     degrees = 70;
  42.     if ( ang == degrees )
  43.     return;
  44.     ang = degrees;
  45.     repaint( cannonRect(), FALSE );
  46.     emit angleChanged( ang );
  47. }
  48.  
  49.  
  50. void CannonField::setForce( int newton )
  51. {
  52.     if ( newton < 0 )
  53.     newton = 0;
  54.     if ( f == newton )
  55.     return;
  56.     f = newton;
  57.     emit forceChanged( f );
  58. }
  59.  
  60.  
  61. void CannonField::shoot()
  62. {
  63.     if ( isShooting() )
  64.     return;
  65.     timerCount = 0;
  66.     shoot_ang = ang;
  67.     shoot_f = f;
  68.     autoShootTimer->start( 50 );
  69.     emit canShoot( FALSE );
  70. }
  71.  
  72.  
  73. void  CannonField::newTarget()
  74. {
  75.     static bool first_time = TRUE;
  76.     if ( first_time ) {
  77.     first_time = FALSE;
  78.     QTime midnight( 0, 0, 0 );
  79.     srand( midnight.secsTo(QTime::currentTime()) );
  80.     }
  81.     QRegion r( targetRect() );
  82.     target = QPoint( 200 + rand() % 190,
  83.              10  + rand() % 255 );
  84.     repaint( r.unite( targetRect() ) );
  85. }
  86.  
  87. void CannonField::setGameOver()
  88. {
  89.     if ( gameEnded )
  90.     return;
  91.     if ( isShooting() )
  92.     autoShootTimer->stop();
  93.     gameEnded = TRUE;
  94.     repaint();
  95. }
  96.  
  97. void CannonField::restartGame()
  98. {
  99.     if ( isShooting() )
  100.     autoShootTimer->stop();
  101.     gameEnded = FALSE;
  102.     repaint();
  103.     emit canShoot( TRUE );
  104. }
  105.  
  106. void CannonField::moveShot()
  107. {
  108.     QRegion r( shotRect() );
  109.     timerCount++;
  110.  
  111.     QRect shotR = shotRect();
  112.  
  113.     if ( shotR.intersects( targetRect() ) ) {
  114.     autoShootTimer->stop();
  115.     emit hit();
  116.     emit canShoot( TRUE );
  117.     } else if ( shotR.x() > width() || shotR.y() > height() ||
  118.         shotR.intersects(barrierRect()) ) {
  119.     autoShootTimer->stop();
  120.     emit missed();
  121.     emit canShoot( TRUE );
  122.     } else {
  123.     r = r.unite( QRegion( shotR ) );
  124.     }
  125.  
  126.     repaint( r );
  127. }
  128.  
  129.  
  130. void CannonField::mousePressEvent( QMouseEvent *e )
  131. {
  132.     if ( e->button() != LeftButton )
  133.     return;
  134.     if ( barrelHit( e->pos() ) )
  135.     barrelPressed = TRUE;
  136. }
  137.  
  138.  
  139. void CannonField::mouseMoveEvent( QMouseEvent *e )
  140. {
  141.     if ( !barrelPressed )
  142.     return;
  143.     QPoint pnt = e->pos();
  144.     if ( pnt.x() <= 0 )
  145.     pnt.setX( 1 );
  146.     if ( pnt.y() >= height() )
  147.     pnt.setY( height() - 1 );
  148.     double rad = atan(((double)rect().bottom()-pnt.y())/pnt.x());
  149.     setAngle( qRound ( rad*180/3.14159265 ) );
  150. }
  151.  
  152.  
  153. void CannonField::mouseReleaseEvent( QMouseEvent *e )
  154. {
  155.     if ( e->button() == LeftButton )
  156.     barrelPressed = FALSE;
  157. }
  158.  
  159.  
  160. void CannonField::paintEvent( QPaintEvent *e )
  161. {
  162.     QRect updateR = e->rect();
  163.     QPainter p( this );
  164.  
  165.     if ( gameEnded ) {
  166.     p.setPen( black );
  167.     p.setFont( QFont( "Courier", 48, QFont::Bold ) );
  168.     p.drawText( rect(), AlignCenter, "Game Over" );
  169.     }
  170.     if ( updateR.intersects( cannonRect() ) )
  171.     paintCannon( &p );
  172.     if ( updateR.intersects( barrierRect() ) )
  173.     paintBarrier( &p );
  174.     if ( isShooting() && updateR.intersects( shotRect() ) )
  175.     paintShot( &p );
  176.     if ( !gameEnded && updateR.intersects( targetRect() ) )
  177.     paintTarget( &p );
  178. }
  179.  
  180. void CannonField::paintShot( QPainter *p )
  181. {
  182.     p->setBrush( black );
  183.     p->setPen( NoPen );
  184.     p->drawRect( shotRect() );
  185. }
  186.  
  187.  
  188. void CannonField::paintTarget( QPainter *p )
  189. {
  190.     p->setBrush( red );
  191.     p->setPen( black );
  192.     p->drawRect( targetRect() );
  193. }
  194.  
  195. void CannonField::paintBarrier( QPainter *p )
  196. {
  197.     p->setBrush( yellow );
  198.     p->setPen( black );
  199.     p->drawRect( barrierRect() );
  200. }
  201.  
  202. const QRect barrelRect(33, -4, 15, 8);
  203.  
  204. void CannonField::paintCannon( QPainter *p )
  205. {
  206.     QRect cr = cannonRect();
  207.     QPixmap pix( cr.size() );
  208.     pix.fill( this, cr.topLeft() );
  209.  
  210.     QPainter tmp( &pix );
  211.     tmp.setBrush( blue );
  212.     tmp.setPen( NoPen );
  213.  
  214.     tmp.translate( 0, pix.height() - 1 );
  215.     tmp.drawPie( QRect( -35,-35, 70, 70 ), 0, 90*16 );
  216.     tmp.rotate( -ang );
  217.     tmp.drawRect( barrelRect );
  218.     tmp.end();
  219.  
  220.     p->drawPixmap( cr.topLeft(), pix );
  221. }
  222.  
  223.  
  224. QRect CannonField::cannonRect() const
  225. {
  226.     QRect r( 0, 0, 50, 50 );
  227.     r.moveBottomLeft( rect().bottomLeft() );
  228.     return r;
  229. }
  230.  
  231.  
  232. QRect CannonField::shotRect() const
  233. {
  234.     const double gravity = 4;
  235.  
  236.     double time      = timerCount / 4.0;
  237.     double velocity  = shoot_f;
  238.     double radians   = shoot_ang*3.14159265/180;
  239.  
  240.     double velx      = velocity*cos( radians );
  241.     double vely      = velocity*sin( radians );
  242.     double x0        = ( barrelRect.right()  + 5 )*cos(radians);
  243.     double y0        = ( barrelRect.right()  + 5 )*sin(radians);
  244.     double x         = x0 + velx*time;
  245.     double y         = y0 + vely*time - 0.5*gravity*time*time;
  246.  
  247.     QRect r = QRect( 0, 0, 6, 6 );
  248.     r.moveCenter( QPoint( qRound(x), height() - 1 - qRound(y) ) );
  249.     return r;
  250. }
  251.  
  252.  
  253. QRect CannonField::targetRect() const
  254. {
  255.     QRect r( 0, 0, 20, 10 );
  256.     r.moveCenter( QPoint(target.x(),height() - 1 - target.y()) );
  257.     return r;
  258. }
  259.  
  260.  
  261. QRect CannonField::barrierRect() const
  262. {
  263.     return QRect( 145, height() - 100, 15, 100 );
  264. }
  265.  
  266.  
  267. bool CannonField::barrelHit( const QPoint &p ) const
  268. {
  269.     QWMatrix mtx;
  270.     mtx.translate( 0, height() - 1 );
  271.     mtx.rotate( -ang );
  272.     mtx = mtx.invert();
  273.     return barrelRect.contains( mtx.map(p) );
  274. }
  275.  
  276.  
  277. bool CannonField::isShooting() const
  278. {
  279.     return autoShootTimer->isActive();
  280. }
  281.  
  282.  
  283. QSize CannonField::sizeHint() const
  284. {
  285.     return QSize( 400, 300 );
  286. }
  287.  
  288.  
  289. QSizePolicy CannonField::sizePolicy() const
  290. {
  291.     return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
  292. }
  293.